package dnl.dtools.grm.vfs;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URISyntaxException;
import java.net.URL;

import org.apache.commons.vfs.FileObject;
import org.apache.commons.vfs.FileSystemException;
import org.apache.commons.vfs.FileSystemManager;
import org.apache.commons.vfs.FileType;
import org.apache.commons.vfs.VFS;

import ajul.lang.Args;
import dnl.dtools.grm.Resource;

/**
 * Represents an entry on a remote file system that is accessed via SSH.
 * 
 * @author Daniel Or
 * 
 */
public class VfsEntry extends Resource {

	private FileObject fileObject;

	private String remotePath;

	// private boolean exists;

	private boolean isDirectory;

	private boolean isArchive;

	private long size;

	private long lastModifTime;

	private VfsEntry parent;


	public VfsEntry(URL url, FileObject fileObject, VfsEntry parent)
	throws URISyntaxException {
		super(url);
		Args.assertNotNull(fileObject);
		this.fileObject = fileObject;
		this.remotePath = url.getFile();
		if (this.remotePath.length() > 1 && this.remotePath.charAt(1) == '~') {
			this.remotePath = this.remotePath.substring(1);
		}
		this.parent = parent;
		System.err.println(url.toString());
	}

	public static VfsEntry from(java.io.File file){ 
		try {
			FileSystemManager fsManager = VFS.getManager();
			FileObject fileObject = fsManager.resolveFile( file.getAbsolutePath());
			return new VfsEntry(fileObject.getURL(), fileObject, null);
		} catch (FileSystemException e) {
			e.printStackTrace();
			return null;
		} catch (URISyntaxException e) {
			e.printStackTrace();
			throw new IllegalStateException();
		}
	}

	public FileObject getFileObject() {
		return fileObject;
	}

	public String getRemotePath() {
		return remotePath;
	}

	
	@Override
	public boolean delete() throws IOException {
		return fileObject.delete();
	}

	@Override
	public boolean exists() {
		return true;
	}

	@Override
	public Resource getChild(String name) {
		try {
			FileObject child = fileObject.getChild(name);
			return new VfsEntry(child.getURL(), child, this);
		} catch (FileSystemException e) {
			e.printStackTrace();
		} catch (URISyntaxException e) {
			e.printStackTrace();
		}
		throw new IllegalStateException();
	}

	@Override
	public InputStream getInputStream() {
		try {
			return fileObject.getContent().getInputStream();
		} catch (FileSystemException e) {
			e.printStackTrace();
			throw new IllegalStateException();
		}
	}
	

	@Override
	public long getLastModified() {
		return lastModifTime;
	}

	@Override
	public OutputStream getOutputStream() {
		try {
			return fileObject.getContent().getOutputStream();
		} catch (FileSystemException e) {
			e.printStackTrace();
			throw new IllegalStateException();
		}
	}

//	private FileObject getGrandParent(){
//		try {
//			FileObject parent = fileObject.getParent();
//			if(parent == null)
//				return null;
//			parent = parent.getParent();
//			return parent;
//		} catch (FileSystemException e) {
//			e.printStackTrace();
//			throw new IllegalStateException();
//		}
//	
//	}
	
	@Override
	public Resource getParent() {
		if(parent == null){
			try {
				FileObject parent = fileObject.getParent();
				if(parent == null)
					return null;
				this.parent = new VfsEntry(parent.getURL(), parent, this);
			} catch (FileSystemException e) {
				e.printStackTrace();
				throw new IllegalStateException();
			} catch (URISyntaxException e) {
				e.printStackTrace();
				throw new IllegalStateException();
			}
		}
		return parent;
	}

	@Override
	public long getSize() {
		return size;
	}

	@Override
	public boolean isArchive() {
		return isArchive;
	}

	@Override
	public boolean isArchiveEntry() {
		return false;
	}		
	
	@Override
	public boolean isDirectory() {
		return isDirectory;
	}

	@Override
	public boolean isHidden() {
		return false;
	}
	
	@Override
	public boolean isLocal() {
		return false;
	}

	private boolean isDirectory(FileObject fo){
		try {
			return FileType.FOLDER.equals(fo.getType());
		} catch (FileSystemException e) {
			e.printStackTrace();
			throw new IllegalStateException();
		}
	}
	
	@Override
	public Resource[] list() {
		try {
			FileObject[] children = fileObject.getChildren();
			VfsEntry[] entries = new VfsEntry[children.length];
			for (int i = 0; i < entries.length; i++) {
				entries[i] = (VfsEntry) getChild(children[i].getName().getBaseName());
				entries[i].isDirectory = isDirectory(children[i]);
				entries[i].lastModifTime = children[i].getContent().getLastModifiedTime();
				if(!entries[i].isDirectory){
					entries[i].size = children[i].getContent().getSize();
				}
			}
			return entries;
		} catch (FileSystemException e) {
			e.printStackTrace();
			throw new IllegalStateException();
		}
	}

	@Override
	public boolean mkDir() throws IOException {
		fileObject.createFolder();
		return true;
	}

	@Override
	public boolean renameTo(Resource dest) throws IOException {
		VfsEntry vfse = (VfsEntry) dest;
		fileObject.moveTo(vfse.getFileObject());
		return true;
	}
	
	public boolean isRoot(){
		return this.remotePath.equals("/");
	}

	@Override
	public String toString() {
		return "VfsEntry{"+remotePath+"}";
	}

	
}
